﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Security.Cryptography;
using SinBiota.Model.Business.AuthenticationServices.Interfaces;
using SinBiota.Model.Business.PersistenceServices.Interfaces;
using SinBiota.Model.Entities;
using SinBiota.Model.Persistence.Repositories.Interfaces;

namespace SinBiota.Model.Business.PersistenceServices.Implementation
{
    public class UserPersistenceServices : IUserPersistenceServices
    {
        private readonly IUserRepository _userRepository;
        private readonly IPasswordResetRequestRepository _passwordResetRepository;
        private readonly IAuthentication _authentication;

        public UserPersistenceServices(IUserRepository userRepository, IPasswordResetRequestRepository passwordResetRepository, IAuthentication authentication)
        {
            _userRepository = userRepository;
            _authentication = authentication;
            _passwordResetRepository = passwordResetRepository;
        }

        public User FindById(int id)
        {
            return _userRepository.FindById(id);
        }

        public IList<User> FindAll()
        {
            return _userRepository.FindAll();
        }

        public void Delete(User user)
        {
            _userRepository.Delete(user);
        }

        public void DeleteById(int id)
        {
            Delete(FindById(id));
        }
        public void Save(User user)
        {
            _userRepository.Save(user);
        }

        public void Update(User editUser)
        {
            _userRepository.Update(editUser);
        }

        public void Update(User editUser, string[] coordinatorField, string[] memberField)
        {
            _userRepository.Update(editUser, coordinatorField, memberField);
        }

        public User FindByUsername(string username)
        {
           return _userRepository.FindByUsername(username);
           
        }

        public User FindByName(string name)
        {
            return _userRepository.FindByName(name);

        }

        public IList<User> FindByEmail(string email)
        {
            return _userRepository.FindByEmail(email);
        }

        public IList<User> FindByNameOrUsernameLike(string search)
        {
            return _userRepository.FindByNameOrUsernameLike(search);
        }

        public IList<Project> ProjectsFromUser(string username)
        {
            var user = _userRepository.FindByUsername(username);
            var list = new List<Project>();
            if (user != null)
            {
                list.AddRange(user.CoordinatorProjects);
                list.AddRange(user.MemberProjects);
            }
            return list;
        }

        public IList<Project> ActiveProjectsFromUser(string username)
        {
            return ProjectsFromUser(username).Where(x => x.ProjectStatus.Equals(ProjectStatus.InProgress)).ToList();
        }

        public string NewPasswordResetRequest(User user)
        {
            var key = _authentication.CreateSalt();
            var hashedKey = _authentication.HashString(user.Username + key);
            _passwordResetRepository.Save(new PasswordResetRequest { RequestDate = DateTime.Now, User = user, ResetKey = hashedKey });
            return key;
        }

        public PasswordResetStatus GetPasswordResetRequestStatus(User user, string key)
        {
            var hashedKey = _authentication.HashString(user.Username + key);
            var request = _passwordResetRepository.FindByEqRestrictionUniqueResult(x => x.ResetKey,  hashedKey);
            if (request == null) return PasswordResetStatus.Notvalid;

            var elapsedDays = DateTime.Now.Subtract(request.RequestDate).TotalDays;
            return elapsedDays > double.Parse(ConfigurationManager.AppSettings["PasswordResetExpiredInDays"]) 
                ? PasswordResetStatus.Expired 
                : PasswordResetStatus.Valid;
        }

        public void RemovePasswordResets(User user)
        {
            foreach (var request in _passwordResetRepository.FindByEqRestrictionListResult(x => x.User, user)) 
            {
                _passwordResetRepository.Delete(request);
            }
        }
    }
}